﻿using Exceptionless;
using Exceptionless.Models;
using Exceptionless.Models.Data;
using Exceptionless.Plugins;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Abp.Auditing
{
    public class ExceptionlessAuditingStore : IAuditingStore
    //, Abp.Dependency.ISingletonDependency
    {
        public IHttpContextAccessor HttpContextAccessor { get; }

        public ExceptionlessAuditingStore(IHttpContextAccessor httpContextAccessor)
        {
            HttpContextAccessor = httpContextAccessor;
        }

        public void Save(AuditInfo auditInfo)
        {
            var builder = CreateEvent(auditInfo);
            builder?.Submit();
        }

        EventBuilder CreateEvent(AuditInfo auditInfo)
        {
            ContextData data = new ContextData();
            var exp = auditInfo.Exception;
            auditInfo.Exception = null;
            var client = ExceptionlessClient.Default;
            EventBuilder builder;
            string content = JsonConvert.SerializeObject(auditInfo);

            if (exp == null)
            {
                builder = client.CreateLog(content, Exceptionless.Logging.LogLevel.Info);
                builder.AddTags(nameof(Exceptionless.Logging.LogLevel.Info));
            }
            else
            {
                builder = client.CreateLog(content, Exceptionless.Logging.LogLevel.Warn);
                builder.AddTags(nameof(Exception), exp.GetType().Name);
                int i = 0;
                do
                {
                    builder.SetProperty($"Exception-{i}", exp.Message);
                    builder.SetProperty($"StackTrace-{i}", exp.StackTrace);
                    exp = exp.InnerException;
                    ++i;
                } while (exp != null);
            }
            //builder.SetProperty(nameof(AuditInfo.ExecutionTime), auditInfo.ExecutionTime);
            //builder.SetProperty(nameof(AuditInfo.ExecutionDuration), auditInfo.ExecutionDuration);
            builder.SetValue(auditInfo.ExecutionDuration);
            builder.AddTags(nameof(Auditing));
            builder.SetSource(nameof(Auditing));
            return builder;
        }

        public Task SaveAsync(AuditInfo auditInfo)
        {
            var builder = CreateEvent(auditInfo);
            builder?.Submit();
            return Task.Delay(0);
        }
    }
}
